package com.lance.answer.question_answer;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.lance.answer.dto.CompleteInfo;
import com.lance.answer.dto.XjCourseVideoInfo;
import com.lance.answer.dto.XjUserCourseInfo;
import com.lance.answer.gui.answer.AnswerObject;
import com.lance.answer.gui.answer.DealJsonString;
import com.lance.answer.gui.answer.Util;
import com.lance.answer.util.Constant;
import com.lance.answer.util.HttpUtil;
import com.lance.answer.util.XinJiangUtil;
import org.apache.commons.io.IOUtils;
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.*;

/**
 * @author fengx
 * 新疆一体化答题-课程作业
 *
 * <p>
 * "questionTitle":"一般较为常见的职业发展路径有两条：##和##。",
 * "questionTitle":"一般较为常见的职业发展路径有两条：和。",
 * 答案中不能出现##号，要替换一下。
 * </p>
 */
public class DoXJAnswerHomework {


    private static List<WebElement> findWeElements(WebDriver driver, String cssSelector, int second) {
        return (new WebDriverWait(driver, Duration.ofSeconds(second))).until((ExpectedCondition<List<WebElement>>)
                d -> {
                    assert d != null;
                    return d.findElements(By.cssSelector(cssSelector));
                });
    }


    public static void main(String[] args) {


        // WebDriver driver = Util.getDriver("d:\\ynouAutoStudy\\chromedriver.exe");
        //   WebDriver driver = Util.getDriver("c:\\ynouAutoStudy\\chromedriver.exe");

//        int openCourseId = 30944;
//        String homeworkName = "职业生涯规划（1）（平时作业）";
//        String majorName = "2021春季 - 行政管理 - 开放";

        // 校验是否提交
        boolean checkoutCommit = true;

//        int openCourseId = 33539;
//        String homeworkName = "个人与团队管理（平时作业）";
//        String majorName = "2021春季 - 工商企业管理 - 开放";

//        int openCourseId = 33544;
//        String homeworkName = "公共关系学（平时作业）";
//        String majorName = "2021春季 - 工商企业管理 - 开放";

//        int openCourseId = 33355;
//        String homeworkName = "心理学概论（平时作业）";
//        String majorName = "2021春季 - 人力资源管理 - 开放";


    //    int openCourseId = 32873;
   //     String homeworkName = "简明新疆历史（平时作业）";
        // String majorName = "2021秋all";
   //     String majorName = "2021秋all2";
    //    String majorName = "2021秋allother";

        int openCourseId = 33651;
     //   String majorName = "2021春季 - 行政管理新疆试点 - 开放";
        String majorName = "2021秋all2";
        String homeworkName = "语文（1）（平时作业）";

//        int openCourseId = 33323;
//        String majorName = "2021春季 -药学 - 开放";
//        String homeworkName = "无机化学（药）（平时作业）";


        /// 12-7
//        int openCourseId = 31005;
//        String majorName = "2021春季 - 计算机信息管理 - 开放";
//        String homeworkName = "工具书与文献检索（平时作业）";

//        int openCourseId = 33311;
//        String majorName = "2021春季 - 计算机信息管理 - 开放";
//        String homeworkName = "数字与图像处理（平时作业）";


//        int openCourseId = 33442;
//        String majorName = "2021春季 -学前教育 - 开放";
//        String homeworkName = "心理学（平时作业）";
//
//                int openCourseId = 33496;
//        String majorName = "2021春季 -学前教育 - 开放";
//        String homeworkName = "幼儿园管理（平时作业）";

//        int openCourseId = 33331;
//        String majorName = "2021春季 -药学 - 开放";
//        String homeworkName = "医学生物化学（平时作业）";
//
//        int openCourseId = 33312;
//        String majorName = "2021春季 - 会计 - 开放";
//        String homeworkName = "经济法律基础（平时作业）";


        //经济法律基础

        /// 12-7
//        int openCourseId = 33338;
//        String majorName = "2021春季 -计算机网络技术（网页设计方向） - 开放";
//        String homeworkName = "网络信息制作与发布（平时作业）";



//        int openCourseId = 33361; //TODO
//        String majorName = "2021秋季 -建设工程管理 - 开放";
//        String homeworkName = "建筑力学（平时作业）";

//        int openCourseId = 33420;
//        String majorName = "2021秋季-行政管理-开放";
//        String homeworkName = "管理心理学（平时作业）";

//        int openCourseId = 33446;
//        String majorName = "2021秋季-机电一体化技术-开放";
//        String homeworkName = "电子商务概论（平时作业）";

//        int openCourseId = 33360;  ///FIXME TODO
//        String majorName = "2021秋季-工商企业管理-开放";
//        String homeworkName = "政治经济学（平时作业）";

//        int openCourseId = 33323;
//        String majorName = "2021秋季 -药学 - 开放";
//        String homeworkName = "无机化学（药）（平时作业）";




        int sync = 1;
        try {


            InputStream inputStream2 = new FileInputStream("D:\\answers\\" + homeworkName + ".json");
            String answerStr = IOUtils.toString(inputStream2, StandardCharsets.UTF_8);
            List<AnswerObject> list = JSONObject.parseArray(answerStr, AnswerObject.class);
            Map<String, AnswerObject> answerMap = Maps.newHashMap();
            for (AnswerObject answerObject : list) {
                answerMap.put(DealJsonString.delHTMLTag(Util.dealContent(answerObject.getQuestionTitle())), answerObject);
            }


            InputStream inputStream3 = new FileInputStream("D:\\answers\\" + majorName + ".user");
            List<String> users = IOUtils.readLines(inputStream3, "utf-8");

            List<List<String>> group = new ArrayList<>();
            int size = users.size();
            int step = size / sync;
            if (step == 0) {
                group.add(users);
            } else {
                for (int i = 0; i < sync; i++) {
                    List<String> list2 = users.subList(step * i, (i + 1) * step);
                    group.add(list2);
                }
                group.add(users.subList(step * sync, users.size()));
            }

            for (List<String> batchUser : group) {
                Constant.THREAD_POOL_BATCH.execute(() -> {
                    try {
                        for (String user : batchUser) {
                            String[] strs = user.split(",");
                            String userCode = strs[0];
                            userCode = userCode.toUpperCase(Locale.ROOT);
//                            String pwd;
                            String pwd =strs[1];
//                            if (userCode.contains("X")) {
//                                pwd = userCode.substring(11, 17);
//                            } else {
//                                pwd = userCode.substring(12);
//                            }
                            completeHomework(majorName, openCourseId, answerMap, checkoutCommit, userCode, pwd);
                        }

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });

            }


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void completeHomework(String majorName, int openCourseId, Map<String, AnswerObject> answerMap, boolean checkoutCommit,
                                        String username, String pwd) throws Exception {



        boolean isComplete = false;
        try{
            String filePath = "E:\\answerInfo一体化\\"+majorName+"\\"+username+".txt";
            File userCompleteInfoFile = new File(filePath);
            InputStream inputStream = new FileInputStream(userCompleteInfoFile);
            String completeInfoStr = IOUtils.toString(inputStream,"UTF-8");
            List<CompleteInfo> completeInfoList = JSONObject.parseArray(completeInfoStr, CompleteInfo.class);
            if(null!=completeInfoList){
                for(CompleteInfo info:completeInfoList){
                    if ("没有这门课程！".equals(info.getSummary())) {
                        isComplete = true;
                        break;
                    }
                }
            }


        }catch (Exception e){
            e.printStackTrace();
        }
        if(isComplete){
            return;
        }


        WebDriver driver = Util.getDriver("c:\\ynouAutoStudy\\chromedriver.exe");

        try {
            int sid = 0;
            driver.get("https://xjskk.open.com.cn/stuspace-auth/#/login");
            XinJiangUtil.studentLogin(driver, username, pwd);
            Thread.sleep(5000);

            try{
                for (WebElement we : findWeElements(driver, "div[class='part']", 20)) {
                    System.err.println("we.getAttribute(\"title\")):" + we.getAttribute("title"));
                    if (majorName.equals(we.getAttribute("title"))) {
                        we.click();
                        break;
                    }
                    // FIXME 正式要删掉
                    if (!Strings.isNullOrEmpty(we.getAttribute("title")) && we.getAttribute("title").contains("2021年秋季")) {
                        we.click();
                        break;
                    }
                    if (!Strings.isNullOrEmpty(we.getAttribute("title")) && we.getAttribute("title").contains("2021年春季")) {
                        we.click();
                        break;
                    }
                    if (!Strings.isNullOrEmpty(we.getAttribute("title")) && we.getAttribute("title").contains("2020年春季")) {
                        we.click();
                        break;
                    }
                    if (!Strings.isNullOrEmpty(we.getAttribute("title")) && we.getAttribute("title").contains("2020年秋季")) {
                        we.click();
                        break;
                    }
                    // FIXME 正式要删掉
                }
            }catch (Exception e1){

            }


//            // FIXME 有的人报了多个专业
//            for (WebElement we : findWeElements(driver, "div[class='part']", 20)) {
//                if (majorName.equals(we.getAttribute("title"))) {
//                    we.click();
//                    Thread.sleep(5000);
//                    break;
//                }
//
//                // FIXME 正式要删掉
//                if (!Strings.isNullOrEmpty(we.getAttribute("title")) && we.getAttribute("title").contains("2021年秋季")) {
//                    we.click();
//                    break;
//                }
//                // FIXME 正式要删掉
//
//            }

            Set<Cookie> cookies = driver.manage().getCookies();
            String studentSpaceProfile = Util.getStudentSpaceProfile2(cookies);
            String authorization = Util.getAuthorization2(cookies);
            Map<String, String> heads = Maps.newHashMap();
            String cookie = Util.getCookie(cookies);
            initHeads(heads, studentSpaceProfile, authorization);

            String getCourseInfoUrl = "https://xjskk.open.com.cn/api/student/student-space-service/courses/" +
                    "getStudentCourses?pageNumber=1&pageSize=2000000&status=1&courseNameCode=";
            XjUserCourseInfo userCourseInfo = JSON.parseObject(HttpUtil.get(getCourseInfoUrl, cookie, heads),
                    XjUserCourseInfo.class);
            for (XjUserCourseInfo.ContentDTO.ItemsDTO items : userCourseInfo.getContent().getItems()) {
                if (openCourseId == items.getOpenCourseId()) {
                    sid = items.getSelectCourseId();
                    break;
                }
            }

            driver.get("https://xjskk.open.com.cn/stuspace/#/course?oId=" + openCourseId + "&sId=" + sid);

            // 获取当前已经刷了的课程项目

            Thread.sleep(5000);
            for (WebElement liWe : findWeElements(driver, "li[class='fl']", 30)) {
                if ("课程作业".equals(liWe.getText().trim())) {
                    liWe.click();
                    break;
                }
            }
            Thread.sleep(5000);


            // v-btn theme--light primary

            int homeworkSize = findWeElements(driver, "button[class='v-btn theme--light primary']", 30).size();
            boolean refresh = false;
            for (int i = 0; i < homeworkSize; i++) {

                if (i>0&&refresh) {
                    driver.navigate().refresh();
                    Thread.sleep(3000);
                    for (WebElement liWe : findWeElements(driver, "li[class='fl']", 30)) {
                        if ("课程作业".equals(liWe.getText().trim())) {
                            liWe.click();
                            break;
                        }
                    }
                    Thread.sleep(10000);
                }

                boolean isCommit = false;
                if (checkoutCommit) {
                    // todo 校验
                    try {
                        List<WebElement> textAreaList = driver.findElement(By.className("work-part1")).findElements(By.className("text"));
                        WebElement textArea = textAreaList.get(i);
                        WebElement webElement = Util.findByClassName(textArea, "status-2");
                        if (webElement != null && webElement.getText().equals("已提交未批阅")) {
                            isCommit = true;
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                if (isCommit) {
                    refresh = false;
                    continue;
                }
                refresh = true;


                // 这里点击按钮时要有一个鼠标下拉的操作，不然点击不到答题
//                if (i > 2) {
//                    ((JavascriptExecutor) driver).executeScript("window.scrollTo(0,100000)");
//                }
                WebElement btnWe = findWeElements(driver, "button[class='v-btn theme--light primary']", 30).get(i);
                Thread.sleep(1000);
                // TODO 开始答题
                btnWe.click();
                Util.switchToLast(driver);
                Thread.sleep(5000);
                // 2、确定答题
                confirmAnswer(driver);
                Thread.sleep(5000);
                // 3、开始答题 TODO list-children-class children-div-top
                List<WebElement> questionWeList = findWeElements(driver, "div[class^='list-children-class']", 20);
                doAnswer(driver, questionWeList, answerMap);
                // FIXME TODO 要提交答案
                // 4、提交测验
                Thread.sleep(3000);
                btnClick(driver, "提交作业");
                Thread.sleep(4000);
                btnClick(driver, "确定");
                Thread.sleep(3000);
                // 答题完成后返回课程目录
                // btnClick(driver, "返回列表");
                Thread.sleep(3000);
                driver.close();
                Thread.sleep(2000);
                Util.switchToFirst(driver);
                Thread.sleep(5000);
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("Exception !!!!!!!!!!!!!!!!!");
        } finally {
            try {
                driver.close();
                driver.quit();
            } catch (Exception e) {

            }
        }
    }

    public static void btnClick(WebDriver driver, String btnName) {
        for (WebElement confirmBtn : driver.findElements(By.cssSelector("button[type='button']"))) {
            if (confirmBtn.getText().equals(btnName)) {
                confirmBtn.click();
                break;
            }
        }
    }


    private static void doAnswer(WebDriver driver, List<WebElement> questionWeList, Map<String, AnswerObject> answerMap) throws Exception {

        // fixme
        Thread.sleep(1000);
        // fixme

        System.err.println("questionWeListSize：" + questionWeList.size());

        Map<String, Integer> ueditorIndexMap = Maps.newHashMap();
        ueditorIndexMap.put("ueditorIndex", 0);
        for (WebElement questionWe : questionWeList) {
            WebElement titleWe = questionWe.findElement(By.className("children-value-class"));
            // fixme
            String title = titleWe.getText();
            title = Util.dealContent(title);
            title = DealJsonString.delHTMLTag(title);
            AnswerObject answerObject = answerMap.get(title);
            if (answerObject == null) {
                System.err.println("答案不存在:" + title);
                // FIXME 如果问题不存在，就用HANLP来匹配
                double similarity = 0.0;
                String answerTitle = "";
                for (Map.Entry<String, AnswerObject> entry : answerMap.entrySet()) {
                    double k1 = DealJsonString.getSimilarity(title, entry.getKey());
                    if (k1 > similarity) {
                        similarity = k1;
                        answerTitle = entry.getKey();
                    }
                }
                System.err.println("answerTitle:" + answerTitle + " similarity:" + similarity);
                // 相似度为0.9 就选择
                if (similarity > 0.60) {
                    answerObject = answerMap.get(answerTitle);
                } else {
                    try {
                        Thread.sleep(20000000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            System.err.println("answerObject:" + JSONObject.toJSONString(answerObject));
            assert answerObject != null;
            String questionType = answerObject.getQuestionType();


            switch (questionType) {
                case "1":
                case "2":
                case "3": {
                    // 单选 多选 判断
                    doChoiceExercise(questionWe, answerObject.getAnswers());
                    break;
                }
                case "4":
                case "6": {
                    doGapFilling(driver, questionWe, answerObject.getAnswers(), ueditorIndexMap);
                    break;
                }
                default: {
                    throw new Exception("不支持的题型!" + questionType + answerObject.getQuestionTitle());
                }
            }
        }
    }

    /**
     * 填空题
     *
     * @param answerElement answerElement
     * @param realAnswers   realAnswers
     */
    private static void doGapFilling(WebDriver driver, WebElement answerElement, List<String> realAnswers,
                                     Map<String, Integer> ueditorIndexMap) {

        try {
            List<WebElement> divList = answerElement.findElements(By.cssSelector("div[class='virtualInput']"));
            System.err.println("divList：Size:" + divList.size());
            for (int i = 0; i < divList.size(); i++) {
                WebElement div = divList.get(i);
                //   input.clear();
                div.click();
                Thread.sleep(2000);
                //  WebElement iframe = driver.findElement(By.id("ueditor_0"));
                Integer index = ueditorIndexMap.get("ueditorIndex");
                WebElement iframe = driver.findElement(By.id("ueditor_" + index));
                System.err.println("realAnswers.get(i):" + realAnswers.get(i));
                String js = "document.getElementById('" + iframe.getAttribute("id") + "').contentWindow.document.body.innerText = '" + realAnswers.get(i) + "'";
                ((JavascriptExecutor) driver).executeScript(js);
                ueditorIndexMap.put("ueditorIndex", ++index);
                //  Thread.sleep(200000);
                //  div.sendKeys( realAnswers.get(i));
                Thread.sleep(2000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private static void doChoiceExercise(WebElement answerElement, List<String> realAnswers) {
        // 遍历题目的每一个选项
        for (WebElement singleAnswerElement : answerElement.findElements(By.cssSelector("div[class='clearfix']"))) {
            String answerContent = singleAnswerElement.
                    findElement(By.cssSelector("span[class='option-value-class']")).getText();
            //兼容特殊字符
            answerContent = Util.dealContent(answerContent);
            System.err.println("answerContent:" + answerContent);
            // 找到单选框或复选框
            // el-checkbox el-radio
            WebElement labelElement = singleAnswerElement.findElement(By.cssSelector("label[class^='el-']"));

            // 找到真正的点击按钮 el-radio__input el-checkbox__input
            WebElement realClickElement = singleAnswerElement.findElement(By.cssSelector("span[class^='el-']"));

            String labelClass = labelElement.getAttribute("class");
            System.err.println("labelClass:" + labelClass);

            // 单选或者判断题
            WebElement clickWebElement = null;
            if (labelClass.contains("radio")) {
                clickWebElement = labelElement.findElement(By.cssSelector("input[type='radio']"));
            }
            if (labelClass.contains("checkbox")) {
                clickWebElement = labelElement.findElement(By.cssSelector("input[type='checkbox']"));
            }
            // FIXME 判断题0：对 1：错
            // 这里的ID是每个选项的ID answerContent是每个选项的内容
            for (String realAnswer : realAnswers) {
                System.err.println("origin:" + answerContent);
                // if (answerContent.equals(realAnswer)) {
                if (DealJsonString.delHTMLTag(answerContent).equals(DealJsonString.delHTMLTag(realAnswer))) {
                    System.err.println("realAnswer:" + realAnswer);
                    assert clickWebElement != null;
                    if (!clickWebElement.isSelected()) {
                        realClickElement.click();
                    }
                }
            }


        }
    }


    public static void initHeads(Map<String, String> heads, String studentSpaceProfile, String authorization) {
        heads.put("referer", "https://xjskk.open.com.cn/stuspace/");
        heads.put("authority", "xjskk.open.com.cn");
        heads.put("path", "/api/student/student-space-service/resources/updateResourceTrace");
        heads.put("scheme", "scheme");
        heads.put("open-student-space-profile", studentSpaceProfile);
        heads.put("origin", "https://xjskk.open.com.cn");
        heads.put("authorization", authorization);
    }

    public static JSONObject initSaveJson(int openCourseId, XjCourseVideoInfo.ContentDTO.ResourcesDTO resources) {
        JSONObject saveJson = new JSONObject();
        // 课程ID，固定的
        saveJson.put("openCourseId", openCourseId);
        // 单个视频的资源ID
        saveJson.put("resourceUid", resources.getResourceUid());
        // 视频总时长
        saveJson.put("totalTime", resources.getTraceTime());
        saveJson.put("traceTime", 0);
        return saveJson;
    }


    public static void clickAnswer(WebDriver driver, XjCourseVideoInfo.ContentDTO.ExaminesDTO examines) {
        // fixme 按理说应该只选择最后一个答题
        for (WebElement span : findWeElements(driver, "span[class='testName font-blue']", 20)) {
            if (span == null || Strings.isNullOrEmpty(span.getText())) {
                continue;
            }
            //    System.err.println("span:" + span.getText());
            // if (span.getText().trim().equals(examines.getName().trim())) {
            if (DealJsonString.delHTMLTag(span.getText()).equals(DealJsonString.delHTMLTag(examines.getName()))) {
                // 点击完成之后要break
                span.click();
                break;
            }
        }
    }

    public static void confirmAnswer(WebDriver driver) {
        List<WebElement> saveButtons = findWeElements(driver, "button[type='button']", 30);
        if (!CollectionUtils.isEmpty(saveButtons)) {
            for (WebElement webElement : saveButtons) {
                String text = webElement.getText();
                System.err.println("text:" + text);
                if (text.contains("确 定")) {
                    webElement.click();
                    break;
                }
            }
        }
    }


}
